home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Mac Format 1995 June
/
MacFormat 25.iso
/
Shareware City
/
Developers
/
OutOfPhase1.1 Source
/
OutOfPhase Folder
/
NLProc.c
< prev
next >
Wrap
Text File
|
1995-01-04
|
10KB
|
275 lines
/* NLProc.c */
/*****************************************************************************/
/* */
/* Out Of Phase: Digital Music Synthesis on General Purpose Computers */
/* Copyright (C) 1994 Thomas R. Lawrence */
/* */
/* This program is free software; you can redistribute it and/or modify */
/* it under the terms of the GNU General Public License as published by */
/* the Free Software Foundation; either version 2 of the License, or */
/* (at your option) any later version. */
/* */
/* This program is distributed in the hope that it will be useful, */
/* but WITHOUT ANY WARRANTY; without even the implied warranty of */
/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */
/* GNU General Public License for more details. */
/* */
/* You should have received a copy of the GNU General Public License */
/* along with this program; if not, write to the Free Software */
/* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
/* */
/* Thomas R. Lawrence can be reached at tomlaw@world.std.com. */
/* */
/*****************************************************************************/
#include "MiscInfo.h"
#include "Audit.h"
#include "Debug.h"
#include "Definitions.h"
#include "NLProc.h"
#include "FastFixedPoint.h"
#include "SampleConsts.h"
#include "NonlinearProcSpec.h"
#include "Memory.h"
#include "WaveTableObject.h"
#include "AlgoWaveTableObject.h"
#include "FloatingPoint.h"
#include "WaveIndexUtility.h"
struct NLProcRec
{
/* number of frames per table */
long FramesPerTable;
/* number of tables */
long NumberOfTables;
/* raw wave table data array */
void** WaveTableMatrix;
/* function for indexing the wave table */
signed long (*WaveIndexer)(float Phase, FastFixedType TableIndex,
long NumTables, long Frames, void** Matrix);
/* stereo flag */
MyBoolean StereoFlag;
/* number of bits */
NumBitsType NumBits;
/* reciprocal of volume scaling factor */
float InverseVolume;
/* state parameters */
float CurrentInputScaling;
float CurrentOutputScaling;
FastFixedType CurrentWaveTableIndex;
/* control parameters */
float InputScaling;
float InputAccent1;
float InputAccent2;
float InputAccent3;
float InputAccent4;
float OutputScaling;
float OutputAccent1;
float OutputAccent2;
float OutputAccent3;
float OutputAccent4;
float WaveTableIndex;
float IndexAccent1;
float IndexAccent2;
float IndexAccent3;
float IndexAccent4;
/* free list link */
NLProcRec* Next;
};
static NLProcRec* NLProcFreeList = NIL;
/* flush free list elements */
void FlushCachedNLProcStuff(void)
{
while (NLProcFreeList != NIL)
{
NLProcRec* Temp;
Temp = NLProcFreeList;
NLProcFreeList = NLProcFreeList->Next;
ReleasePtr((char*)Temp);
}
}
/* create a new nonlinear processor */
NLProcRec* NewNLProcProcessor(struct NonlinProcSpecRec* Template,
MyBoolean StereoFlag, float InverseVolume)
{
NLProcRec* NLProc;
CheckPtrExistence(Template);
if (NLProcFreeList != NIL)
{
NLProc = NLProcFreeList;
NLProcFreeList = NLProcFreeList->Next;
}
else
{
NLProc = (NLProcRec*)AllocPtrCanFail(sizeof(NLProcRec),"NLProcRec");
if (NLProc == NIL)
{
FailurePoint1:
return NIL;
}
}
NLProc->InverseVolume = InverseVolume;
switch (GetNLProcSpecWaveType(Template))
{
default:
EXECUTE(PRERR(ForceAbort,"NewNLProcProcessor: invalid nlproc wavetable type"));
break;
case eNLDataWaveTable:
{
WaveTableObjectRec* DataWaveTable;
long Index;
DataWaveTable = GetNLProcSpecDataWaveTable(Template);
CheckPtrExistence(DataWaveTable);
NLProc->NumberOfTables = WaveTableObjectGetNumTables(DataWaveTable);
NLProc->FramesPerTable = WaveTableObjectEntriesPerTable(DataWaveTable);
NLProc->NumBits = WaveTableObjectGetNumBits(DataWaveTable);
NLProc->WaveTableMatrix = (void**)AllocPtrCanFail(sizeof(void*)
* NLProc->NumberOfTables,"Wave table vector");
if (NLProc->WaveTableMatrix == NIL)
{
FailurePoint2:
ReleasePtr((char*)NLProc);
goto FailurePoint1;
}
for (Index = 0; Index < NLProc->NumberOfTables; Index += 1)
{
PRNGCHK(NLProc->WaveTableMatrix,&(((void**)(NLProc->WaveTableMatrix))[
Index]),sizeof(((void**)(NLProc->WaveTableMatrix))[Index]));
((void**)(NLProc->WaveTableMatrix))[Index]
= WaveTableObjectGetRawSlice(DataWaveTable,Index);
}
}
break;
case eNLAlgoWaveTable:
{
AlgoWaveTableObjectRec* AlgoWaveTable;
long Index;
AlgoWaveTable = GetNLProcSpecAlgoWaveTable(Template);
CheckPtrExistence(AlgoWaveTable);
NLProc->NumberOfTables = AlgoWaveTableObjectGetNumTables(AlgoWaveTable);
NLProc->FramesPerTable = AlgoWaveTableObjectGetNumFrames(AlgoWaveTable);
NLProc->NumBits = AlgoWaveTableObjectGetNumBits(AlgoWaveTable);
NLProc->WaveTableMatrix = (void**)AllocPtrCanFail(sizeof(void*)
* NLProc->NumberOfTables,"Wave table vector");
if (NLProc->WaveTableMatrix == NIL)
{
FailurePoint2a:
goto FailurePoint2;
}
for (Index = 0; Index < NLProc->NumberOfTables; Index += 1)
{
PRNGCHK(NLProc->WaveTableMatrix,&(((void**)(NLProc->WaveTableMatrix))[
Index]),sizeof(((void**)(NLProc->WaveTableMatrix))[Index]));
((void**)(NLProc->WaveTableMatrix))[Index]
= AlgoWaveTableObjectGetRawSlice(AlgoWaveTable,Index);
}
}
break;
}
switch (NLProc->NumBits)
{
default:
EXECUTE(PRERR(ForceAbort,"NewLFOGenerator: bad num bits"));
break;
case eSample8bit:
NLProc->WaveIndexer = (signed long (*)(float,
FastFixedType,long,long,void**))&WaveTable8Bit;
break;
case eSample16bit:
NLProc->WaveIndexer = (signed long (*)(float,
FastFixedType,long,long,void**))&WaveTable16Bit;
break;
}
NLProc->StereoFlag = StereoFlag;
NLProc->InputScaling = GetNLProcInputScaling(Template);
NLProc->InputAccent1 = GetNLProcInputAccent1(Template);
NLProc->InputAccent2 = GetNLProcInputAccent2(Template);
NLProc->InputAccent3 = GetNLProcInputAccent3(Template);
NLProc->InputAccent4 = GetNLProcInputAccent4(Template);
NLProc->OutputScaling = GetNLProcOutputScaling(Template);
NLProc->OutputAccent1 = GetNLProcOutputAccent1(Template);
NLProc->OutputAccent2 = GetNLProcOutputAccent2(Template);
NLProc->OutputAccent3 = GetNLProcOutputAccent3(Template);
NLProc->OutputAccent4 = GetNLProcOutputAccent4(Template);
NLProc->WaveTableIndex = GetNLProcWaveTableIndex(Template);
NLProc->IndexAccent1 = GetNLProcIndexAccent1(Template);
NLProc->IndexAccent2 = GetNLProcIndexAccent2(Template);
NLProc->IndexAccent3 = GetNLProcIndexAccent3(Template);
NLProc->IndexAccent4 = GetNLProcIndexAccent4(Template);
return NLProc;
}
/* dispose of the nonlinear processor */
void DisposeNLProcProcessor(NLProcRec* NLProc)
{
CheckPtrExistence(NLProc);
ReleasePtr((char*)NLProc->WaveTableMatrix);
NLProc->Next = NLProcFreeList;
NLProcFreeList = NLProc;
}
/* update nonlinear state with accent information */
void UpdateNLProcState(NLProcRec* NLProc, float Accent1, float Accent2,
float Accent3, float Accent4)
{
float Temp;
CheckPtrExistence(NLProc);
/* multiply by NLProc->InverseVolume to undo the division everyone else does */
NLProc->CurrentInputScaling = (NLProc->InputScaling + Accent1 * NLProc->InputAccent1
+ Accent2 * NLProc->InputAccent2 + Accent3 * NLProc->InputAccent3
+ Accent4 * NLProc->InputAccent4) * NLProc->InverseVolume;
/* divide by NLProc->InverseVolume to restore the correct volume, and by */
/* MAX16BIT to correct for value returned from wave index routine */
NLProc->CurrentOutputScaling = (NLProc->OutputScaling + Accent1 * NLProc->OutputAccent1
+ Accent2 * NLProc->OutputAccent2 + Accent3 * NLProc->OutputAccent3
+ Accent4 * NLProc->OutputAccent4) / (NLProc->InverseVolume * MAX16BIT);
Temp = NLProc->WaveTableIndex + Accent1 * NLProc->IndexAccent1
+ Accent2 * NLProc->IndexAccent2 + Accent3 * NLProc->IndexAccent3
+ Accent4 * NLProc->IndexAccent4;
NLProc->CurrentWaveTableIndex = Double2FastFixed(Temp);
}
/* apply nonlinear processing to some stuff */
void ApplyNLProc(largefixedsigned* Data, long NumFrames, NLProcRec* NLProc)
{
long Scan;
CheckPtrExistence(Data);
CheckPtrExistence(NLProc);
if (NLProc->StereoFlag)
{
NumFrames *= 2;
}
for (Scan = 0; Scan < NumFrames; Scan += 1)
{
float Temp;
PRNGCHK(Data,&(Data[Scan]),sizeof(Data[Scan]));
Temp = (*NLProc->WaveIndexer)((1 + largefixed2single(Data[Scan])
* NLProc->CurrentInputScaling) / 2 * (NLProc->FramesPerTable - 1),
NLProc->CurrentWaveTableIndex,NLProc->NumberOfTables,
NLProc->FramesPerTable,NLProc->WaveTableMatrix)
* NLProc->CurrentOutputScaling;
Data[Scan] = double2largefixed(Temp);
}
}